﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Cost.Models;
using NBlock.Core.ORM;
using NBlock.Core;

namespace Cost.Services
{
    /// <summary>
    /// 订单服务类
    /// </summary>
    public class OrderService
    {
        #region 构造函数
        private readonly ICostRepository<ReportedOrder> reportedOrderRepository;
        private readonly ICostRepository<DishOrder> dishOrderRepository;
        private readonly ICostRepository<DishOrderItem> dishOrderItemRepository;
        private readonly ICostRepository<DishMaterial> dishMaterialRepository;
        private readonly ICostRepository<MaterialOrderItem> materialOrderItemRepository;
        private readonly MaterialService materialService;
        private readonly IEnumService enumService;
        public OrderService(ICostRepository<ReportedOrder> reportedOrderRepository,
            ICostRepository<DishOrder> dishOrderRepository,
            ICostRepository<DishOrderItem> dishOrderItemRepository,
            ICostRepository<DishMaterial> dishMaterialRepository,
            ICostRepository<MaterialOrderItem> materialOrderItemRepository,
            MaterialService materialService,
            IEnumService enumService)
        {
            this.dishOrderRepository = dishOrderRepository;
            this.reportedOrderRepository = reportedOrderRepository;
            this.dishOrderItemRepository = dishOrderItemRepository;
            this.dishMaterialRepository = dishMaterialRepository;
            this.materialOrderItemRepository = materialOrderItemRepository;
            this.materialService = materialService;
            this.enumService = enumService;

        }
        #endregion

        /// <summary>
        /// 获取下周订单，如果上报订单不存在则创建一个，同时创建7日订单，每次都会更新订单的总成本
        /// </summary>
        /// <param name="Id"></param>
        /// <returns></returns>
        public ReportedOrder GetWeekOrder(string Id)
        {
            var order = this.reportedOrderRepository.Find(Id);
            if (order == null)
            {
                var siteId = nbUserContext.Current.CurrentUser.UnitCode;
                var dayOfWeek = (double)DateTime.Today.DayOfWeek;
                dayOfWeek = dayOfWeek <= 0 ? 7 : dayOfWeek;
                var beginDate = DateTime.Today.AddDays(8 - dayOfWeek);
                var endDate = DateTime.Today.AddDays(15 - dayOfWeek).AddMilliseconds(-10);

                // 判断指定上报订单（周订单）是否存在！
                var weekOrder = reportedOrderRepository.Find(w => w.SiteId == siteId && w.BeginDate == beginDate && w.EndDate == endDate);
                if (weekOrder == null)
                {
                    weekOrder = new ReportedOrder
                    {
                        OrderName = string.Format("{0}月第{1}周的订单", beginDate.Month, WeekOfMonth(beginDate)),
                        Status = "草稿",
                        BeginDate = beginDate,
                        EndDate = endDate,
                        SiteId = nbUserContext.Current.CurrentUser.UnitCode,
                        SiteName = nbUserContext.Current.CurrentUser.UnitName,
                    };
                    reportedOrderRepository.Insert(weekOrder);

                    // 创建7天的每日订单
                    var dishOrderCoount = dishOrderRepository.FindAll(d => d.SiteId == siteId
                        && d.State == "正式订单" && d.OrderDate >= beginDate && d.OrderDate <= endDate).Count();
                    if (dishOrderCoount == 0)
                    {
                        for (var date = beginDate; date <= endDate; )
                        {
                            var dishorder = new DishOrder
                            {
                                OrderDate = date,
                                OrderType = "正式订单",
                                State = "草稿",
                                SiteId = nbUserContext.Current.CurrentUser.UnitCode,
                                SiteName = nbUserContext.Current.CurrentUser.UnitName,
                            };
                            dishOrderRepository.Insert(dishorder);
                            date = date.AddDays(1);
                        }
                    }
                }
                else
                {
                    // 查找周订单关联的每日订单
                    var ids = dishOrderRepository
                        .FindAll(d => d.SiteId == siteId && d.OrderDate >= weekOrder.BeginDate && d.OrderDate <= weekOrder.EndDate)
                        .Select(o => o.Id);

                    var totalCost = dishOrderItemRepository.FindAll(o => ids.Contains(o.OrderId)).Sum(o => (decimal?)o.TotalCost);
                    weekOrder.TotalCost = totalCost.HasValue ? totalCost.Value : 0;
                    reportedOrderRepository.Update(weekOrder);
                }

                order = weekOrder;
            }
            return order;
        }

        /// <summary>
        /// 上报订单（周订单）
        /// </summary>
        public void ReportWeekOrder(ReportedOrder weekOrder)
        {
            if (weekOrder.Status == "上报")
                throw new Exception("订单已经上报，无效操作！");

            // 查找周订单关联的每日订单
            var orders = dishOrderRepository.FindAll(d => d.SiteId == weekOrder.SiteId
                && d.OrderDate >= weekOrder.BeginDate && d.OrderDate <= weekOrder.EndDate).ToList();

            var orderIds = orders.Select(o => o.Id);
            var totalCost = dishOrderItemRepository.FindAll(o => orderIds.Contains(o.OrderId)).Sum(o => (decimal?)o.TotalCost);
            weekOrder.TotalCost = totalCost.HasValue ? totalCost.Value : 0;
            weekOrder.Status = "上报";
            weekOrder.ReportDate = DateTime.Now;
            reportedOrderRepository.Update(weekOrder);

            foreach (var order in orders)
            {
                order.ReportUserId = weekOrder.ReportUserId;
                order.ReportUserName = weekOrder.ReportUserName;
                ReportOrder(order);
            }
        }

        /// <summary>
        /// 上报订单
        /// </summary>
        public void ReportOrder(DishOrder order)
        {
            if (order.State == "上报")
                throw new Exception("订单已经上报，无效操作！");

            order.State = "上报";
            order.ReportDate = DateTime.Now;
            dishOrderRepository.Update(order);

            // 更新菜肴的状态
            var items = dishOrderItemRepository.FindAll(item => item.OrderId == order.Id).ToList();
            foreach (var item in items)
            {
                item.State = "上报";
                dishOrderItemRepository.Update(item);

                // 保存菜肴的配比品名的状态
                var materials = materialOrderItemRepository.FindAll(m => m.ItemId == item.Id).ToList();
                foreach (var m in materials)
                {
                    m.State = "上报";
                    materialOrderItemRepository.Update(m);
                }
            }

            // 设置订单的预计总价和菜肴汇总
            var names = items.Select(item => item.Name).Distinct().ToArray();
            order.ItemDesc = string.Join(",", names);
            order.TotalCost = items.Sum(item => item.TotalCost);
        }

        /// <summary>
        ///  保存每日订单，会重新保存菜肴明细，而菜肴对应的配比每次都是清空之后重新添加的
        /// </summary>
        /// <param name="order"></param>
        /// <param name="items"></param>
        public void SaveDishOrder(DishOrder order, IList<DishOrderItem> items)
        {
            if (order.State == "上报")
                throw new Exception("订单已经上报，无效操作！");

            if (string.IsNullOrWhiteSpace(order.SiteName))
                order.SiteName = enumService.GetEnumText("ProjectSite", order.SiteId);
            dishOrderRepository.Save(order);

            // 如果菜肴明细为null，则直接跳过！
            if (items == null)
                return;

            // 保存菜肴明细
            foreach (var item in items)
            {
                if (item.CreateDate.Ticks == 0)
                {
                    item.SiteId = order.SiteId;
                    item.OrderId = order.Id;
                    item.Date = order.OrderDate;
                    item.State = "草稿";
                }
                item.TotalCost = item.Count * item.DishCost;
                dishOrderItemRepository.Save(item);

                // 清空菜肴对应的所有明细
                materialOrderItemRepository.DeleteAll(m => m.OrderId == item.OrderId && m.ItemId == item.Id);

                // 保存菜肴的配比数据
                var materials = dishMaterialRepository.FindAll(d => d.DishId == item.DishId).ToList();
                foreach (var m in materials)
                {
                    var mItem = new MaterialOrderItem
                    {
                        OrderId = item.OrderId,
                        ItemId = item.Id,
                        SiteId = item.SiteId,
                        Date = order.OrderDate,
                        DishId = m.DishId,
                        MaterialId = m.MaterialId,
                        Code = m.Code,
                        Name = m.Name,
                        NeedProcess = m.NeedProcess,
                        Price = materialService.GetMaterialPrice(m.MaterialId, m.NeedProcess, item.Date),
                        OrderCount = item.Count * m.Weight / int.Parse(m.Unit),
                        State = "草稿",
                    };
                    materialOrderItemRepository.Insert(mItem);
                };
            }

            // 设置订单的预计总价和菜肴汇总
            var names = items.Select(item => item.Name).Distinct().ToArray();
            order.ItemDesc = string.Join(",", names);
            order.TotalCost = items.Sum(item => item.TotalCost);
        }

        /// <summary>
        /// 删除指定Id的订单
        /// </summary>
        /// <param name="orderId"></param>
        public void DeleteDishOrder(string orderIds)
        {
            var ids = orderIds.Split(',');
            var orders = dishOrderRepository.FindAll(o => ids.Contains(o.Id)).ToList();
            if (orders.Exists(o => o.State == "上报"))
                throw new Exception("有些订单已经上报，无效操作！");

            foreach (var order in orders)
            {
                // 删除订单信息
                dishOrderRepository.Delete(order);

                // 删除订单明细
                DeleteDishOrderItem(order.Id);
            }
        }

        /// <summary>
        /// 删除指定Id的订单明细（菜肴）
        /// </summary>
        /// <param name="itemIds">一个或者多个Id，如果订单值为All，则说明需要删除整个订单，故不需要更新订单的信息</param>
        /// <param name="orderId">订单Id</param>
        public void DeleteDishOrderItem(string orderId, string itemIds = "All")
        {
            var order = dishOrderRepository.Find(orderId);
            if (order == null)
                return;

            if (order.State == "上报")
                throw new Exception("订单已经上报，无效操作！");

            // 获取指定订单Id的所有订单明细（菜肴）
            var list = dishOrderItemRepository.FindAll(item => item.OrderId == orderId).ToList();

            var deletedList = list;
            if (itemIds != "All")
            {
                var ids = itemIds.Split(',');
                deletedList = list.FindAll(item => ids.Contains(item.Id));
            }
            if (deletedList != null && deletedList.Count > 0)
            {
                foreach (var item in deletedList)
                {
                    dishOrderItemRepository.Delete(item);

                    // 清空菜肴对应的所有明细
                    materialOrderItemRepository.DeleteAll(m => m.ItemId == item.Id);
                }

                if (itemIds != "All")
                {
                    // 更新每日订单的状态、预计总价和菜肴汇总
                    var items = list.FindAll(item => !deletedList.Any(d => d.Id == item.Id));
                    var names = items.Select(item => item.Name).Distinct().ToArray();
                    order.ItemDesc = string.Join(",", names);
                    order.TotalCost = items.Sum(item => item.TotalCost);
                    dishOrderRepository.Save(order);
                }
            }
            else if (itemIds != "All")
            {
                throw new Exception(string.Format("找不到指定Id（{0}）的订单明细的菜肴信息", itemIds));
            }
        }

        private int WeekOfMonth(DateTime day)
        {
            string y = day.Year.ToString();
            string m = day.Month.ToString();
            string s = y + "-" + m + "-1";

            DateTime dt = DateTime.Parse(s);

            int d = day.Day - dt.Day;
            return int.Parse(Math.Ceiling(d * 1.0 / 7).ToString());
        }

        public void SyncMaterialPrice(DateTime date)
        {
            // 清空菜肴对应的所有明细
            var items = materialOrderItemRepository.FindAll(m => m.Date == date);

            foreach (var item in items)
            {
                item.Price = materialService.GetMaterialPrice(item.MaterialId, item.NeedProcess, item.Date);
                materialOrderItemRepository.Update(item);
            };
        }
    }
}
